/**
 * @Description: rsbuild 配置
 * @Author bianpengfei
 * @create 2024/7/30 11:55
 */
import { defineConfig } from '@rsbuild/core'
import { pluginVue } from '@rsbuild/plugin-vue'
import path2 from 'node:path'
import { IS_PRO, TRANSPILE_DEPENDENCIES, getScriptInfo, getMetaInfo, getLinkInfo } from '@internal/scripts/utils'
import { pluginLess } from '@rsbuild/plugin-less'
import { pluginBabel } from '@rsbuild/plugin-babel'
import { pluginVueJsx } from '@rsbuild/plugin-vue-jsx'
import { pluginSass } from '@rsbuild/plugin-sass'
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'
import dayjs from 'dayjs'
import pkg from './package.json'
import topPkg from '../../package.json'
import { getIpAddrSync } from 'sf-utils2/lib/nodejs/index.js'
import env from './env/index'
import { pluginMockServer } from 'rspack-plugin-mock/rsbuild'
import pluginTransformSvg2 from '@internal/scripts/rsbuild-plugin/plugin-transform-svg2/index'
import pluginBabelParser2 from '@internal/scripts/rsbuild-plugin/plugin-babel-parser2/index'
import gradientString from 'gradient-string'
// import AutoImport from 'unplugin-auto-import/webpack'
// import Components from 'unplugin-vue-components/webpack'
// import {VxeResolver, VxeTableResolver} from '@vxecli/import-unplugin-vue-components'
// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin'
import VueMacrosPlugin from 'unplugin-vue-macros/rspack'

// types
import type { HtmlConfig } from '@rsbuild/core'
// @ts-expect-error
import type { ProxyOptions } from '@rsbuild/core/dist-types/types'

const assetPrefix = IS_PRO ? './' : './'
const SVG_PATH = path2.join(__dirname, 'src/assets/svg')
const port = 8005
/**
 * 动态的插入ejs html
 * @type {{css: *[], external: string[], title: string, script: string[]}}
 */
const inject = {
  external: {},
  script: getScriptInfo([] as any, { publicPath: assetPrefix }),
  link: getLinkInfo([], { publicPath: assetPrefix }),
  meta: getMetaInfo([])
}

export default defineConfig({
  dev: {
    lazyCompilation: false,
    progressBar: {
      id: gradientString('cyan', 'magenta').multiline(`应用`)
    },
    client: {
      port
    }
  },

  server: {
    port,
    open: false,
    strictPort: true,
    host: '0.0.0.0',
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Cache-Control': 'private, no-store, no-cache, must-revalidate, proxy-revalidate'
    },
    proxy: Object.values(env.proxy).reduce(
      (pre, cur) => ({ ...(pre as object), [cur?.['prefix']]: cur['rule'] }),
      {}
    ) as ProxyOptions
  },

  html: ((): HtmlConfig => {
    return {
      template: path2.join(__dirname, 'public/index.html'),
      templateParameters: (() => ({
        script: inject.script.join('\n'),
        link: inject.link.join('\n'),
        meta: inject.meta.join('\n'),
        buildTime: `[${pkg.name}]：${dayjs().format('YYYY-MM-DD HH:mm:ss')} version：${topPkg.version}`
      }))(),
      inject: 'body',
      scriptLoading: 'blocking'
    }
  })(),

  source: {
    define: {
      PUBLIC_URL: JSON.stringify(assetPrefix),
      'process.env.APP_MODE': JSON.stringify(process.env.APP_MODE),
      'process.env.IP': JSON.stringify(getIpAddrSync()),
      'process.env.ENV': JSON.stringify(env!.envEncode),
      'process.env.ENV_MAP': JSON.stringify(env!.envMapEncode),
      'process.env.ENV_PROXY': JSON.stringify(env!.proxyEncode)
    },

    include: TRANSPILE_DEPENDENCIES,

    transformImport: [
      {
        libraryName: 'sf-utils2',
        camelToDashComponentName: false,
        transformToDefaultImport: true,
        customName: `sf-utils2/lib/{{ member }}`
      }
      // {
      //   libraryName: 'vxe-table',
      //   camelToDashComponentName: true,
      //   transformToDefaultImport: true,
      //   customName: `vxe-table/lib/{{ kebabCase member }}`,
      //   customStyleName: `vxe-table/lib/{{ kebabCase member }}`,
      // },
    ]

    // alias: {
    //   '@root/': path2.join(__dirname),
    //   "@/": path2.join(__dirname, 'src'),
    //   "@store/": path2.join(__dirname, 'src/store')
    // }
  },

  environments: {
    // node 环境配置
    node: {
      source: {
        alias: IS_PRO
          ? {
              '@root/': path2.join(__dirname),
              vue$: path2.join(__dirname, 'public/cdn/vue/3.2.37/vue.esm-browser.prod.js')
            }
          : {
              '@root/': path2.join(__dirname)
            }
      }
    }
  },

  output: {
    assetPrefix,
    externals: inject.external,
    // dataUriLimit: {},
    injectStyles: true,
    sourceMap: {
      js: IS_PRO ? false : 'eval-cheap-module-source-map',
      css: !IS_PRO
    },
    cleanDistPath: true,
    minify: IS_PRO,
    polyfill: IS_PRO ? 'usage' : 'off'
  },

  plugins: [
    pluginBabelParser2(),
    pluginTransformSvg2(),
    pluginMockServer({}),
    pluginLess({
      lessLoaderOptions: {
        lessOptions: {
          javascriptEnabled: true,
          modifyVars: {
            hack: `true; @import "~@shared/style/app/vars.less";
            @import "~@shared/style/app/transition.less";
            @import "~@shared/style/app/mixin.less";
            `
          }
        }
      }
    }),
    pluginSass({
      sassLoaderOptions: {
        additionalData: '@use "@shared/style/element-plus/index.scss" as *;',
        warnRuleAsWarning: false
      }
    }),
    pluginVue(),
    pluginBabel({
      include: /\.(?:jsx|tsx)/
      // exclude: /[\\/]node_modules[\\/]/
    }),
    pluginVueJsx(),
    pluginNodePolyfill()
  ],

  performance: {
    prefetch: {
      exclude: () => true // 排除所有
    },
    chunkSplit: {
      strategy: 'split-by-size'
    },
    printFileSize: IS_PRO,
    bundleAnalyze: IS_PRO
      ? {
          openAnalyzer: process.env.ANALYZER == 'true'
        }
      : null,
    removeConsole: IS_PRO
  },

  tools: {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    rspack(config, { env }) {
      // if (env === 'development') {
      //   config.devtool = 'eval-cheap-module-source-map'
      // }
      // return {
      //   resolve: {
      //     alias: {
      //       '@util': 'src/util',
      //     },
      //   },
      // };

      // perf: 添加dev缓存，更快builder，热启动
      config.cache = true

      // @ts-expect-error
      config.experiments.cache ||= {}
      const experimentsCache = config.experiments.cache as Record<string, any>
      experimentsCache.type = 'persistent'

      config.experiments.parallelCodeSplitting = true

      config.output.chunkLoadingGlobal = `webpackJsonp_${pkg?.name}`
      config.output.library = `${pkg.name}-[name]`
      config.output.libraryTarget = `umd`
      config.resolve.alias ||= {}

      // feat 支持qiankun
      config.output.chunkLoadingGlobal = `webpackJsonp_${pkg?.name}`
      config.resolve.alias ||= {}
      config.plugins.push(VueMacrosPlugin())
      return config
    },

    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    bundlerChain: (config, { CHAIN_ID }) => {
      config.module
        .rule(CHAIN_ID.RULE.SVG)
        .exclude.add(SVG_PATH)
        .end()
        .end()
        .rule('svg-sprite-loader')
        .test(/\.svg$/)
        .include.add(SVG_PATH) // 处理svg目录
        .end()
        .use('svg-sprite-loader')
        .loader('svg-sprite-loader')
        .options({
          symbolId: (filePath) => {
            const relativePath = path2.relative(SVG_PATH, filePath)
            return relativePath.replace(/\.\//, '').replace(/[\\/]/g, '/').replace('.svg', '')
          }
        })
        .end()
        .after(CHAIN_ID.RULE.SVG)

      // const includeFn = (filePath) => TRANSPILE_DEPENDENCIES.some((reg) => reg.test(filePath))
      // config.module.rule('vue').include.add(includeFn).add(path2.join(JEPLUS_PATH, 'zsamc-operate'))
    }
  }
})
